iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
自我挑戰組

菜雞們,讓我們一起征服JS及React吧系列 第 12

React菜雞-Day12:React Hook第二招 ~ Context 開啟資源共享的時代

  • 分享至 

  • xImage
  •  
tags: 鐵人賽 React javascript nodejs vscode

鐵人賽第十二天,今天突然來了爆量的工作,一直忙到下班前,才有空檔;多虧通勤時規劃好內容,才能如行雲流水般的寫完文章。

先聊聊資料傳遞的概念

  • 我們在鐵人賽第七天-React Hook 起手式 ~ useState聊到useState,定義好的statestateFunc,我們可以使用props往下傳遞;第二層、第三層應該都沒問題,那 第n層呢?

  • 再思考一個,隨著前端設計的越來越複雜,compoent定義在不同的JS檔中,要如何搞定這問題呢?/images/emoticon/emoticon04.gif

  • 為了解決這個問題,Context登高一呼,號令大家說~「我把state、stateFunc及其他資源都放在這個global區域,你們儘管到這取用,別跑遠了!/images/emoticon/emoticon24.gif

四個步驟,建立起每個component的共享空間

  • 使用方法很簡單
  • Step1: 先透過createContext建立一個物件appStore,這個物件通常建立在global區,並透過export將這個物件,提供給其他檔案import使用。
  • Step2: 將剛剛建立的物件,以標籤語言包裝你的巢狀的Component**
  • Step3: 在剛剛的標籤語言內,定義你要傳遞的值在標籤參數value,以Object的形式包裝
// app.js
Import {createContext} from “React”
export const appStore

function TopComp(){
  ...
  
  return(
    <appStore.Provider value={{以Object的方式,放入你要傳遞的東西,ex: state, func, reducer...等}}>
      <你的巢狀Components />
      ...
    </appStore.Provider>
  )
  
}
  • Step4: 其他JS檔案,先透過importappStore引入,接著,在function component裡面,使用useContext來存取上層定義的資源
import {useContext} from "react";
import {appStore} from "./app.js"


function CompA(){
  const receivedGlobalData = useContext(appStore);
  //=== 取得資料後,即可開始使用 ===
  return(){...};
}

用一個例子來說明/images/emoticon/emoticon77.gif

  • 不囉唆,直接用一個例子來實戰一下,我想提供使用者一個input,使用者可以透過input輸入文字,並顯示到一個<h1>的文字區中。
  1. 先建立一個資料夾/src/components/ContextExample
  2. 新增並編輯檔案/src/components/ContextExample/Message.js,以建立顯示文字的元件
// src/components/ContextExample/Message.js

import React, { createContext, useState } from "react"; //<-- (1)import createContext 準備使用
import Input from "./Input";
export const MsgStore = createContext(); //<--(2)在這裡建立一個context物件,並export出去,預備給其他component使用

export default function Message() {
  const initTitle = "React Rookie's 30 days";
  
  const [titleText, setTitleText] = useState(initTitle); //(3)<--useState設定
  
  //(4)<MsgStore value={}>標籤符號,搭配value傳送物件
  return (
    <MsgStore.Provider
      value={{ titleState: titleText, titleFunc: setTitleText }}
    >
      <h2>{titleText?titleText:setTitleText(initTitle)}</h2>
      <Input />
    </MsgStore.Provider>
  );
}

  1. 新增並編輯/src/components/ContextExample/input.js,建立輸入的元件
//input.js
//(1) 定義一個<input>,提供輸入文字,
//(2) 呼叫useContext來取得app.js的global資料,
//(3) 並運用<input>的onChange的事件與app.js的title互動顯示

import React, { useContext } from "react"; //<--(1) 引用 useContext
import { MsgStore } from "./Message";

export default function Input() {
  const { titleState, titleFunc } = useContext(MsgStore); //<--(2) 傳遞時用object, 因此接收時,也是以object的型態,接收titleState及titleFunc
  console.log("get titleState from Context:" + titleState); 
  
  // (3)定義一個<input>,提供輸入文字
  //    並運用<input>的onChange的事件與app.js的title互動顯示
  return (
    <>
      <input onChange={(e) => titleFunc(e.target.value)}></input>
    </>
  );
}

  1. 編輯index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Message from "./components/ContextExample/Message";

ReactDOM.render(
  <Message/>,
  document.getElementById('root')
);

跑起來看看 /images/emoticon/emoticon12.gif

  • 初始畫面

  • input中打文字,可以看到,因為onChange事件的運用,讓我們可以每打一個字,就更新在<h1>的title處。

結論

  • React Context建立了一個共享空間,讓狀態能夠在components之間交流,就像建立了一個中央控制台,統一操作、傳遞、交流;未來當我們的前端架構越來越複雜時,context能幫我們省事不少,還不給個讚
  • 鐵人賽第12天,你的React實力又往前邁進了一大步,今晚,就來點鼎泰豐的小籠包,給自己犒賞一番
    /images/emoticon/emoticon62.gif

上一篇
React菜雞-Day11:學會JS獨特的用法,讓你的React更優雅-第四篇 拷貝還有分深淺
下一篇
React菜雞-Day13:React Hook第3招 ~ useReducer讓你有降龍十八掌般的招式
系列文
菜雞們,讓我們一起征服JS及React吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言